#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define instr_recs  instr_recs0
#define ext_instr_recs  ext_instr_recs0
#define x87_instr_recs  x87_instr_recs0
#include "instr_dat.h"

static struct instr_rec instr_desc;

//
// class of operand format
//

enum OPERCLASS{
	NONE,IMM16plusIMM8,IMM8,IMM16,IMM,RorM,RorMplusIMM8,RorMplusIMM,Ronly,Monly,Addr,Ptr16_32};




//
//    16bitaddress instr patterns:
//    1)  opcode 1/2 +rm+ disp0/8/16 + imm8/16: length2~7 bytes
//    2)  opcode 1/2 +rel8/16: length2~4 bytes
//    3)  opcode 1/2+ ptr 16:16: length 5~6
//    4)  opcode 1+imm16+imm8 ; length 4
//    5)  opcode imm16: length 3
//    6)  opcode 1/2imm8 : length 2~3
//    6)  opcode disp16 : length 3
//
//    16bitaddress instr patterns:
//    1)  opcode 1/2 +rm+ disp0/8/16/32 + imm8/16/32: length2~11 bytes
//    2)  opcode 1/2 +rel8/16/32: length2~6 bytes
//    3)  opcode 1/2+ ptr 16:16: length 5~6
//    4)  opcode 1+imm16+imm8 ; length 4
//    5)  opcode imm16/32: length 5
//    6)  opcode 1/2 imm8 : length 2~3
//    6)  opcode disp1/326 : length 5
//
//
//
static int get_instr_desc(unsigned char * opcode);
static int get_ext_instr_desc(unsigned char * opcode);
static int mk_flag(OPERAND_TYPE op_type);
static int basic_len(int flag);
static char * op_str(OPERAND_TYPE op_type);

static  enum OPERCLASS get_flag(OP_FMT fmt);

FILE *fp;

enum OPERCLASS flags_instr_recs[sizeof (instr_recs)/sizeof (instr_recs[0])];
enum OPERCLASS flags_ext_instr_recs[sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0])];
enum OPERCLASS flags_x87_instr_recs[sizeof (x87_instr_recs)/sizeof (x87_instr_recs[0])];
static void print_case()
{



	if (0xff==instr_desc.mask)
		fprintf(fp,"||( 0x%x==code[0]// %s   %s %s\n",instr_desc.id,instr_desc.mnemonics,op_str(instr_desc.src1),op_str(instr_desc.src2));
	else
		fprintf(fp,"||( 0x%x==(code[0]& 0x%x)// %s   %s %s\n",instr_desc.id,instr_desc.mask,instr_desc.mnemonics,op_str(instr_desc.src1),op_str(instr_desc.src2));

	//
	//id2
	//
	if (0xff!=instr_desc.id2)
	{
			fprintf(fp,"&&0x%x==((code[1]>>3)&7) \n",instr_desc.id2);
	}

	//
	//pmodeonly?
	//
	if (instr_desc.pmodeonly)
		fprintf(fp,"&&pmode \n");

	//
	//lockable?
	//
	if (!instr_desc.lockable)
		fprintf(fp,"&&0==(prefix&PREFIX_LOCK) \n");
	//
	//repeatable?
	//
	if (!instr_desc.repeatable)
		fprintf(fp,"&&0==(prefix&(PREFIX_REPZ| PREFIX_REPNZ))\n");


}


static void print_caseb()
{
    print_case();

	if (instr_desc.w_mask==2)
	fprintf(fp,"&&(2==(code[0]& 0x%x)\n",instr_desc.w_mask);
	else if (instr_desc.w_mask)
	fprintf(fp,"&&(0==(code[0]& 0x%x)\n",instr_desc.w_mask);

	if (instr_desc.sext_mask)
	fprintf(fp,"||(0!=(code[0]& 0x%x))\n",instr_desc.sext_mask);
	fprintf(fp,")\n");

}

static void print_casew()
{
    print_case();
	if (instr_desc.w_mask==2)
	fprintf(fp,"&&(0==(code[0]& 0x%x))\n",instr_desc.w_mask);
	else if (instr_desc.w_mask)
	fprintf(fp,"&&(0!=(code[0]& 0x%x))\n",instr_desc.w_mask);


	if (instr_desc.sext_mask)
	fprintf(fp,"&&(0==(code[0]& 0x%x))\n",instr_desc.sext_mask);
}

static void print_casex()
{



	if (0xff==instr_desc.mask)
		fprintf(fp,"||( 0x0F==code[0]&&0x%x==code[1]// %s   %s %s\n",instr_desc.id,instr_desc.mnemonics,op_str(instr_desc.src1),op_str(instr_desc.src2));
	else
		fprintf(fp,"||( 0x0F==code[0]&&0x%x==(code[1]& 0x%x)// %s   %s %s\n",instr_desc.id,instr_desc.mask,instr_desc.mnemonics,op_str(instr_desc.src1),op_str(instr_desc.src2));

	//
	//id2
	//
	if (0xff!=instr_desc.id2)
		fprintf(fp,"&&0x%x==((code[2]>>3)&7) \n",instr_desc.id2);

	//
	//pmodeonly?
	//
	if (instr_desc.pmodeonly)
		fprintf(fp,"&&pmode \n");

	//
	//lockable?
	//
	if (!instr_desc.lockable)
		fprintf(fp,"&&0==(prefix&PREFIX_LOCK) \n");
	//
	//repeatable?
	//
	if (!instr_desc.repeatable)
		fprintf(fp,"&&0==(prefix&(PREFIX_REPZ| PREFIX_REPNZ))\n");


}
static void print_casebx()
{
    print_casex();

	if (instr_desc.w_mask)
	fprintf(fp,"&&(0==(code[1]& 0x%x)\n",instr_desc.w_mask);

	if (instr_desc.sext_mask)
	fprintf(fp,"||(0!=(code[1]& 0x%x))\n",instr_desc.sext_mask);
	fprintf(fp,")\n");

}

static void print_casewx()
{
    print_casex();
	if (instr_desc.w_mask)
	fprintf(fp,"&&0!=(code[1]& 0x%x)\n",instr_desc.w_mask);
	if (instr_desc.sext_mask)
	fprintf(fp,"&&0!=(code[1]& 0x%x)\n",instr_desc.sext_mask);
}

static void print_case_x87()
{
	fprintf(fp,"||( 0x%x==code[0]// %s   %s %s\n",instr_desc.id,instr_desc.mnemonics,op_str(instr_desc.src1),op_str(instr_desc.src2));
	
	//
	//id2
	//
	if (0xff!=instr_desc.id2)
	{
		if (instr_desc.mask==0xff)
			fprintf(fp,"&&0x%x==code[1]",instr_desc.id2);
		else
		fprintf(fp,"&& 0x%x==(code[1]& 0x%x)",instr_desc.id2,instr_desc.mask);

	}
}

//
// single byte instructions
//

void print_1byte_instr()
{

	fprintf(fp," if(false             //  single byte instructions\n");
	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{
	instr_desc = instr_recs[i];
		
	if(flags_instr_recs[i]== NONE)
		{
			
			print_case();
			fprintf(fp," )\n");
		}
	}


	fprintf(fp," ){             // such as sti\n");

	fprintf(fp," len= 1;\n");


	fprintf(fp," }else\n");
}


//
// two bytes instructions
//  0f opcode
//  opcode rm_nomem
//  opcode imm8
// x87:STxx/none/AX/
//

void print_2bytes_instr()
{


	//
	// 0f xx
	//
	fprintf(fp," if(false             //  0f xx\n");
	for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
	{
	instr_desc = ext_instr_recs[i];
		
	if(flags_ext_instr_recs[i]== NONE)
		{
			
			print_casex();
			fprintf(fp," )\n");
		}
	}

	//
	// x87.
	//
	for(int i=0; i <sizeof (x87_instr_recs)/sizeof (x87_instr_recs[0]);i++)
	{
		instr_desc = x87_instr_recs[i];
		
		if(flags_x87_instr_recs[i]== NONE)
		{
			
			print_case_x87();
		    fprintf(fp," )   //  x87, non-mem\n");
		}
		else 
		{
			
			print_case_x87();
			fprintf(fp," &&3==(3&(code[1]>>6) ))   //  opcode rm_reg only\n");

		}
	}

	fprintf(fp," //  xx imm8,such as jnz rel8 \n");
	// xx imm8/rel8
	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{
		instr_desc = instr_recs[i];
			
		if(flags_instr_recs[i]== IMM8)
		{
			
			print_case();
			fprintf(fp," )\n");

		}
	}

	fprintf(fp," //  xx r,imm8,byte mode such as push imm8 \n");
	// xx imm8
	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{
	instr_desc = instr_recs[i];
		
	if(flags_instr_recs[i]== IMM&& instr_desc.w_mask)
		{
			
			print_caseb();
			fprintf(fp," )\n");

		}
	}
	fprintf(fp," //  xx r, such as add reg,reg \n");
	// xx rm_nomem

	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{
	instr_desc = instr_recs[i];
		
	if(flags_instr_recs[i]== Ronly)
		{
			
			print_case();
		fprintf(fp," &&3==(3&(code[1]>>6) ))   //  opcode rm_reg only\n");

		}
	}




	fprintf(fp," ){             // xx imm8/rel8/rm_r\n");

	fprintf(fp," len= 2;\n");


	fprintf(fp," }else\n");

}


//
// three bytes instructions
//  0f opcode rm_nomem
//  opcode imm16
//

void print_3bytes_instr()
{

	fprintf(fp," if(false\n             //  xx imm16: e.g. retf 0x0a\n");

	// xx imm16 e.g. retf 0x0a
	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{
	instr_desc = instr_recs[i];
		
	if(flags_instr_recs[i]== IMM16)
		{
			
			print_case();
			fprintf(fp," )\n");
		}
	}
	//
	// 0f xx rm_nomem
	fprintf(fp,"// 0f opcode rm_no-mem\n");
	for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
	{
	instr_desc =ext_instr_recs[i];
		
	if(flags_ext_instr_recs[i]== Ronly)
		{
			
			print_casex();
			fprintf(fp," )    // 0f opcode rm_reg only\n");

		}
	}
	for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
	{
	instr_desc =ext_instr_recs[i];
		
	if(flags_ext_instr_recs[i]== RorM)
		{
			
			print_casex();
			fprintf(fp,"&&3==((code[2]>>6)&3) )    // 0f opcode rm_reg only\n");

		}
	}
	fprintf(fp,"//  xx imm8\n");
	for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
	{
		instr_desc =ext_instr_recs[i];
		
		if(flags_ext_instr_recs[i]== IMM8)
		{
			
			print_casex();
			fprintf(fp," )    // 0f opcode rm_reg only\n");

		}
	}
	fprintf(fp," ){             // such as retf imm16\n");

	fprintf(fp," len= 3;\n");


	fprintf(fp," }else\n");

}



//
//  case instructionswith rm only
//
//

void print_rm_mm()
{
	fprintf(fp," if(false\n             //  xx rm no imm\n");
	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{

		
		if(flags_instr_recs[i]== RorM)
		{
			instr_desc = instr_recs[i];
			print_case();
			fprintf(fp," )\n");
		}
	}
	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{

		
		if(flags_instr_recs[i]== Monly)
		{
			instr_desc = instr_recs[i];
			print_case();
			fprintf(fp," &&3!=(3&(code[1]>>6)) )    //  opcode rm_mm only\n");
		}
	}
	//
	// x87.
	//
	for(int i=0; i <sizeof (x87_instr_recs)/sizeof (x87_instr_recs[0]);i++)
	{

		
		if(flags_x87_instr_recs[i]== Monly)
		{
			instr_desc = x87_instr_recs[i];
			print_case_x87();
			fprintf(fp," &&3!=(3&(code[1]>>6)) )    //  x87  rm_mm only\n");
		}
	}
	fprintf(fp," ){             //  length  depends on address size\n");

	fprintf(fp," len= (addr_size==32)?mm_noimm_32:(addr_size==16)?mm_noimm_16:0;\n");


	fprintf(fp," }else\n");


}


//
//  case instructionswith rm only
//
//
void print_rm_mmx()
{
	fprintf(fp," if(false\n             // 0f xx noimm\n");
	for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
	{

	
		if(flags_ext_instr_recs[i]== RorM)
		{
			instr_desc = ext_instr_recs[i];
			print_casex();
			fprintf(fp," )\n");
		}
	}

	for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
	{

		
		if(flags_ext_instr_recs[i]== Monly)
		{
			instr_desc = ext_instr_recs[i];
			print_casex();
		fprintf(fp," &&3!=((code[2]>>6)&3))    //  opcode rm_mm only\n");
		}
	}


	fprintf(fp," ){             //  length  depends on address size\n");

	fprintf(fp," len= (addr_size==32)?mm_noimm_32x:(addr_size==16)?mm_noimm_16x:0;\n");


	fprintf(fp," }else\n");


}
//
//  case instructionswith rm ,imm8
//
//

void print_rm_imm8()
{
		fprintf(fp," if(false\n             //  xx rm imm8\n");
		for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
		{
		instr_desc = instr_recs[i];
			
		if(flags_instr_recs[i]== RorMplusIMM8)
			{
				
				print_case();
				fprintf(fp," )\n");
			}
		}
		for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
		{
		instr_desc = instr_recs[i];
			
		if(flags_instr_recs[i]== RorMplusIMM&&0!=instr_desc.w_mask)
			{
				
				print_caseb();
				fprintf(fp," )\n");
			}
		}




		fprintf(fp," ){             //  length  depends on address size\n");

		fprintf(fp," len= (addr_size==32)?mm_imm8_32:(addr_size==16)?mm_imm8_16:0;\n");

		fprintf(fp," }else\n");

}

void print_rm_imm8x()
{
		fprintf(fp," if(false\n             // 0f  xx rm imm8\n");
		for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
		{
		instr_desc = ext_instr_recs[i];
			
		if(flags_ext_instr_recs[i]== RorMplusIMM8)
			{
				
				print_casex();
				fprintf(fp," )\n");
				}
		}

		for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
		{
		instr_desc = ext_instr_recs[i];
			
		if(flags_ext_instr_recs[i]== RorMplusIMM&&instr_desc.w_mask)
			{
				
				print_casebx();
				fprintf(fp," )\n");
				}
		}
		fprintf(fp," ){             //  length  depends on address size\n");

		fprintf(fp," len= (addr_size==32)?mm_imm8_32x:(addr_size==16)?mm_imm8_16x:0;\n");

		fprintf(fp," }else\n");

}


//
//  case instructionswith rm ,imm
//
//

void print_rm_imm()
{
		fprintf(fp," if(false\n             //  xx rm imm\n");
		for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
		{
		    instr_desc = instr_recs[i];
			
		    if((flags_instr_recs[i]== RorMplusIMM))
			{
				
				print_casew();
			fprintf(fp," )\n");
			}
		}


		fprintf(fp," ){             //  length  depends on address size\n");

		fprintf(fp," len= len_rm_imm;\n");
 
		fprintf(fp," }else\n");

}

void print_rm_immx()
{
		fprintf(fp," if(false\n             // 0f xx rm imm\n");
		for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
		{
		    instr_desc = ext_instr_recs[i];
			
		    if((flags_ext_instr_recs[i]== 0x81&&!instr_desc.w_mask))
			{
				
				print_casewx();
				fprintf(fp," )\n");
			}
		}

		fprintf(fp," ){             //  length  depends on address size\n");

		fprintf(fp," len= len_rm_immx;\n");



		fprintf(fp," }else\n");

}
//
//  case instructionswith imm. imm8 is covered in
//
//

void print_imm()
{
		fprintf(fp," if(false\n             //  xx  imm\n");

		for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
		{
		    instr_desc = instr_recs[i];
			
		    if(flags_instr_recs[i]== IMM)
			{
				
				print_casew();
				fprintf(fp," )\n");

			}
		}


		fprintf(fp," ){             //  length  depends on data size\n");

		fprintf(fp," len= data_size==32?5:data_size==16?3:0;\n");
 
		fprintf(fp," }else\n");

}

void print_immx()
{
		fprintf(fp," if(false\n             // 0f  xx  imm\n");

		for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
		{
		    instr_desc = ext_instr_recs[i];
			
		    if(flags_ext_instr_recs[i]== IMM)
			{
				
				print_casewx();
				fprintf(fp," )\n");

			}
		}


		fprintf(fp," ){             //  length  depends on data size\n");

		fprintf(fp," len= data_size==32?6:data_size==16?4:0;\n");
 
		fprintf(fp," }else\n");

}

int gen_instr_len()
{

	//
	//
	//

 //   memset( flags_instr_recs,0,sizeof(flags_instr_recs));
  //  memset( flags_ext_instr_recs,0,sizeof(flags_ext_instr_recs));

	for(int i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
	{
	instr_desc = instr_recs[i];
	flags_instr_recs[i]=get_flag(instr_desc.op_fmt);
	}

	for(int i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
	{
	instr_desc = ext_instr_recs[i];
	flags_ext_instr_recs[i]= get_flag(instr_desc.op_fmt);
	}
	for(int i=0; i <sizeof (x87_instr_recs)/sizeof (x87_instr_recs[0]);i++)
	{
	instr_desc = x87_instr_recs[i];
	flags_x87_instr_recs[i]= get_flag(instr_desc.op_fmt);
	}



	fp = fopen("\\project\\disasmx86\\COMMON\\decode_instr_len0.cpp","wt");
	if(fp)
	{
		int  flag=0;
        int i;
		fprintf(fp,"#include < common.h>\n\n");
		fprintf(fp," int decode_len_mm_imm_16_16 (char*code);\n");
		fprintf(fp," int decode_len_mm_imm_16_16x(char*code);\n");
		fprintf(fp," int decode_len_mm_imm_32_16 (char*code);\n");
		fprintf(fp," int decode_len_mm_imm_32_16x(char*code);\n");
		fprintf(fp," int decode_len_mm_imm_16_32 (char*code);\n");
		fprintf(fp," int decode_len_mm_imm_16_32x(char*code);\n");
		fprintf(fp," int decode_len_mm_imm_32_32 (char*code);\n");
		fprintf(fp," int decode_len_mm_imm_32_32x(char*code);\n");
		fprintf(fp," int decode_len_mm_noimm_16 (char*code);\n"); 
		fprintf(fp," int decode_len_mm_noimm_16x(char*code);\n");
		fprintf(fp," int decode_len_mm_noimm_32 (char*code);\n"); 
		fprintf(fp," int decode_len_mm_noimm_32x(char*code);\n");
		fprintf(fp," int decode_len_mm_imm8_32 (char*code);\n");
		fprintf(fp," int decode_len_mm_imm8_32x(char*code);\n");
		fprintf(fp," int decode_len_mm_imm8_16 (char*code);\n");
		fprintf(fp," int decode_len_mm_imm8_16x(char*code);\n");
		fprintf(fp," int decode_length(int addr_size, int data_size ,unsigned char * code,bool pmode,bool &illegal,char prefix)\n {\n");

		fprintf(fp," int mm_imm_16_32 =decode_len_mm_imm_16_32 (code+1);\n");
		fprintf(fp," int mm_imm_16_32x=decode_len_mm_imm_16_32x(code+2);\n");
		fprintf(fp," int mm_imm_32_32 =decode_len_mm_imm_32_32 (code+1);\n");
		fprintf(fp," int mm_imm_32_32x=decode_len_mm_imm_32_32x(code+2);\n");		

		fprintf(fp," int mm_imm_16_16 =decode_len_mm_imm_16_16 (code+1);\n");
		fprintf(fp," int mm_imm_16_16x=decode_len_mm_imm_16_16x(code+2);\n");
		fprintf(fp," int mm_imm_32_16 =decode_len_mm_imm_32_16 (code+1);\n");
		fprintf(fp," int mm_imm_32_16x=decode_len_mm_imm_32_16x(code+2);\n");

		fprintf(fp," int mm_noimm_32 =decode_len_mm_noimm_32 (code+1);\n");
		fprintf(fp," int mm_noimm_32x=decode_len_mm_noimm_32x(code+2);\n");
		fprintf(fp," int mm_noimm_16 =decode_len_mm_noimm_16 (code+1);\n"); 
		fprintf(fp," int mm_noimm_16x=decode_len_mm_noimm_16x(code+2);\n");
		fprintf(fp," int mm_imm8_32 =decode_len_mm_imm8_32 (code+1);\n");
		fprintf(fp," int mm_imm8_32x=decode_len_mm_imm8_32x(code+2);\n");
		fprintf(fp," int mm_imm8_16 =decode_len_mm_imm8_16 (code+1);\n");
		fprintf(fp," int mm_imm8_16x=decode_len_mm_imm8_16x(code+2);\n");

		fprintf(fp," int len_rm_immx= (addr_size==32)?(data_size==32?mm_imm_32_32x:mm_imm_32_16x):\n"
	               "                                (data_size==32?mm_imm_16_32x:mm_imm_16_16x);\n");


		fprintf(fp," int len_rm_imm= (addr_size==32)?(data_size==32?mm_imm_32_32:mm_imm_32_16):\n"
	               "                               (data_size==32?mm_imm_16_32:mm_imm_16_16);\n");



		fprintf(fp," int len;\n");

		print_1byte_instr();
		print_2bytes_instr();
		print_3bytes_instr();
		print_rm_imm8();
		print_rm_imm8x();
		print_rm_imm();
		print_rm_immx();
		print_imm();
		print_immx();
		print_rm_mm();
		print_rm_mmx();
		for(i=0; i <sizeof (instr_recs)/sizeof (instr_recs[0]);i++)
		{
			char *s;
			instr_desc = instr_recs[i];
			switch(flags_instr_recs[i])
			{
			//
			// rel defined by data_size
			//imm_far defined by data_size
			// mem_off defined by addr_size
			//  imm defined by data_size and sign-extended
			case Ptr16_32: 
				s="len=data_size==16?5:data_size==32?7:0;// ptr16:16/32 depending on operand size\n";
				break;
			case Addr: 
				s="len=(addr_size==16)?3:(addr_size==32)?5:0;//disp16/32 depending on address size \n";
				break;
			case IMM16plusIMM8: 
				s="len=4;//onlyenter \n";
				break;
			default:continue;
			}
			fprintf(fp," if(false\n ");	
			print_case();
			fprintf(fp,"))\n{%s\n}else\n",s);
		}

		for(i=0; i <sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]);i++)
		{
			char *s;

			instr_desc = ext_instr_recs[i];
			switch(flags_ext_instr_recs[i])
			{
			//
			// rel defined by data_size
			//imm_far defined by data_size
			// mem_off defined by addr_size
			//  imm defined by data_size and sign-extended
			case Ptr16_32: 
				s="len=data_size==16?5:data_size==32?7:0;// ptr16:16/32 depending on operand size\n";
				break;
			case Addr: 
				s="len=(addr_size==16)?3:(addr_size==32)?5:0;//disp16/32 depending on address size \n";
				break;
				default:continue;
			}
			fprintf(fp," if(false\n ");	
			print_casex();
			fprintf(fp,"))\n{%s\n}else\n",s);
		}

	     fprintf(fp,"  {\n"
			        "      len=0;\n"
					"      illegal=true;// illegal instr \n"
                    "   }\n"
		    	    "   return len;\n}");
		fclose(fp);
		return 0;
	}

	return 1;
}


int get_ext_instr_desc(unsigned char * opcode)
{
	int j;
	for (j=0; j<sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]); j++) {
			if ((opcode[1] & ext_instr_recs[j].mask) == ext_instr_recs[j].id
				&& (ext_instr_recs[j].id2 == 0xff
					|| ((opcode[2]>>3)&7) == ext_instr_recs[j].id2) ) {

				instr_desc = ext_instr_recs[j];

				return 1;
			}
		}
	return 0;
}

int get_instr_desc(unsigned char * opcode)
{
	int j;
		for (j=0; j<sizeof (instr_recs)/sizeof (instr_recs[0]); j++) {
			if ((opcode[0] & instr_recs[j].mask) ==instr_recs[j].id
				&& (instr_recs[j].id2 == 0xff
					|| ((opcode[1]>>3)&7) == instr_recs[j].id2) ) {

				instr_desc = instr_recs[j];
				return 1;
			}

	}

	return 0;// bad instr
}



int mk_flag(OPERAND_TYPE op_type)
{
int flag=0;

switch (op_type)
{
case acc     :    
case reg_dx  :   
case reg_cl  :  
case const_1 :  
case const_3 :  
case sreg    : 
case reg     :

case none      :
case imp_al     :
case imp_ah     :
case imp_ax     :
case imp_acc    :
case imp_hacc   :
case imp_dacc   :
case dontcare   :
case op1       :
case fs_gs     : 
	break;	
case rm1      :  
case rm2      :  
case rm8      :  
case rm16     :  
case rmf      :  
case rm_r16   :  
case rm_r32   :  
case rm_cr     : 
case rm_dr     : 
case rm_tr     : 
case rm_sreg   : 
	flag = 0x1;
	break;

case imm_8     :
case rel_8     : 
	flag = 0x2;
	break;
case imm_16    :
case rel_16    :
	flag = 0x4;
	break;
case mem_off   : 
	flag = 0x10;
	break;
case imm_far   : 
	flag = 0x20;
	break;
case rel       : 
	flag = 0x4;
	break;
case imm       : 
	flag = 0x80;
	break;
}

return flag;
}


int basic_len(int flag)
{
	int len=1;

	if (flag&0x1)len++; //rm
	if (flag&0x2)len++; //imm8 or rel8
	if (flag&0x4)len+=2; //imm16

	return len;
}

char * op_str(OPERAND_TYPE op_type)
{
char*s="";

switch (op_type)
{
case acc     :    s="acc";break;
case reg_dx  :    s="dx";break;  
case reg_cl  :   s="cl";break;  
case const_1 :    s="1";break; 
case const_3 :   s="3";break;  
case sreg    :    s="sreg";break;
case reg     :   s="r";break;

case imp_al     :   s="al";break;
case imp_ah     :   s="ah";break;
case imp_ax     :   
case imp_acc    :
case imp_hacc   :
case imp_dacc   :   s="acc";break;
case dontcare   :
case op1       :
case none      :   s="";break;


case fs_gs     :    s="fs/gs";break;

case rm1      :  
case rm2      :  
case rm8      :  
case rm16     :  
case rmf      : s="rm";break;
 
case rm_r16   :  
case rm_r32   :  s="r";break; 
case rm_cr     : s="cr";break; 
case rm_dr     :  s="dr";break;
case rm_tr     : s="tr";break; 
case rm_sreg   : s="sreg";break; 
case imm_8     : s="imm8";break;
case rel_8     :  s="rel8";break;
case imm_16    : s="imm16";break;
case rel_16    : s="rel";break;
case mem_off   : s="[disp]";break; 

case imm_far   :  s="ptr16:16/32";break;

case rel       : s="rel";break; 

case imm       :  s="imm";break;

}

return s;
}


enum OPERCLASS get_flag(OP_FMT fmt)
{

	enum OPERCLASS flag=NONE;

	switch(fmt)
	{

case dx_acc	   :
	break; 
case accEv	   :flag=RorM;
	break; 
case accIb	   :flag=IMM8;// out acc,imm8
	break;   
case accIv 	   :flag=IMM;
	break;   
case accReg	   :
	break;    
case accXv     :
	break;  
case Ap	       :flag=Ptr16_32;
	break;     
case DXXv      :
	break;    
case Eb		   :flag=RorM;
	break;    
case Ep		   :flag=Monly;//mem only
	break;     
case Ev		   :flag=RorM;
	break;     
case Ev1	   :flag=RorM;
	break;    
case EvCL	   :flag=RorM;
	break;  
case EvvGv:
case EvGv	   :flag=RorM;
	break;    
case EvGvCL	   :flag=RorM;
	break;    
case EvGvIb    :flag=RorMplusIMM8;//imm8
	break;    
case EvGvIv	   :flag=RorMplusIMM;//imm
	break;    
case EvIb	   :flag=RorMplusIMM8;
	break;    
case EvIv	   :flag=RorMplusIMM;
	break;    
case Ew		   :flag=RorM;
	break;    
case EwGw	   :flag=RorM;
	break;    
case FSGS	   :
	break;    
case Fv		   :
	break;    
case GvEw      :flag=RorM;
	break;    
case GvMa	   :
case GvMv	   :
	flag=Monly;
	break;    
case GvMp	   :flag=Monly;
	break;    
case Ib		   :flag=IMM8;
	break;    
case Ibacc	   :flag=IMM8;// in imm8,acc
	break;    
case int3	   :
	break;    
case Iv		   :flag=IMM;
	break;    
case Iw		   :flag=IMM16;
	break;    
case IwIb	   :flag=IMM16plusIMM8;
	break;    
case Jb		   :flag=IMM8;
	break;    
case Jv		   :flag=IMM;
	break;    
case Mv		   :
case Mp		   :flag=Monly;//mem only
	break;    
case Ms		   :flag=Monly;//mem only
	break;    
case Ovacc	   :flag=Addr;//address size
	break;    
case RdCd	   :flag=Ronly;//reg only
	break;    
case RdDd	   :flag=Ronly;//reg only
	break;    
case RdTd	   :flag=Ronly;//reg only
	break;    
case fmt_REG	   :
	break;    
case regIv	   :flag=IMM;
	break;    
case fmt_SREG	   :
	break;    
case SwEw      :flag=RorM;//reg only
	break;    
case XvYv      :
	break;    
case Yvacc     :
	break;    
case YvDX      :
	break;    
case mem10d	:
case mem10r	:
case mem14	:
case mem2i	:
case mem4i	:
case mem4r	:
case mem8i	:
case mem8r	:
case mem94	:
case mem108	:
	flag=Monly;//mem only
	break;
case fmt_AX	:
case ST0	    :
case ST0i	:
case ST1	    :
case ST2	    :
case STi	    :
case STi0	:
case fmt_none:
case acc_dx:
case fmt_xlat:
	break;
default:
	assert(0);

	}

	return flag;
}




